package com.bankcard.util;

public class CardNumberFormatter {
    private CardNumberFormatter() {
        // Private constructor to prevent instantiation
    }

    public static String removeNonDigits(String input) {
        return input.replaceAll("\\D", "");
    }

    public static String format(String cardNumber) {
        String cleaned = removeNonDigits(cardNumber);
        StringBuilder formatted = new StringBuilder();
        for (int i = 0; i < cleaned.length(); i++) {
            if (i > 0 && i % 4 == 0) {
                formatted.append(" ");
            }
            formatted.append(cleaned.charAt(i));
        }
        return formatted.toString();
    }

    /**
     * Formats a card number according to a specified pattern.
     *
     * @param cardNumber The card number to be formatted. Can contain non-digit characters which will be removed.
     * @param pattern    The pattern to format the card number. Use '0' for digits from the card number,
     *                   '*' for masked digits, and any other character as a literal in the output.
     * @return A formatted string representing the card number according to the given pattern.
     *         The returned string is trimmed of any trailing spaces.
     *
     * @throws IllegalArgumentException if cardNumber or pattern is null
     *
     * @example
     * <pre>
     * String cardNumber = "1234567890123456";
     * String pattern = "0000 **** **** 0000";
     * String formatted = CardNumberFormatter.formatWithPattern(cardNumber, pattern);
     * // formatted will be "1234 **** **** 3456"
     * </pre>
     */
    public static String formatWithPattern(String cardNumber, String pattern) {
        String cleaned = removeNonDigits(cardNumber);
        StringBuilder formatted = new StringBuilder();
        int cardIndex = 0;

        for (char c : pattern.toCharArray()) {
            if (cardIndex >= cleaned.length()) {
                break;
            }

            if (c == '0') {
                formatted.append(cleaned.charAt(cardIndex));
                cardIndex++;
            } else if (c == '*') {
                formatted.append('*');
                cardIndex++;
            } else {
                formatted.append(c);
            }
        }

        return formatted.toString().trim();
    }
}